#pragma once
#include<functional>
#include"Socket.hpp"
#include"InetAddr.hpp"
#include"Log.hpp"

using namespace socket_ns;

const static uint16_t gport = 8888;

using service_t = std::function<std::string(std::string &requeststr)>;

class TcpSever
{
public:
    TcpSever(service_t service,  uint16_t port = gport)
        :_service(service)
        ,_port(port)
        ,_listensock(std::make_shared<TcpSocket>())
        ,_isrunning(false)
    {
        _listensock->BuildListenSocket(_port);
    }

  
    //内部类
    class ThreadData
    {
    public:
        SockSPtr _sockfd;
        TcpSever* _self;
        InetAddr _addr;
    public:
        ThreadData(SockSPtr sockfd, TcpSever* self, const InetAddr& addr)
            :_sockfd(sockfd)
            ,_self(self)
            ,_addr(addr)
        {}
    };

    void Loop() 
    {
        //signal(SIGCHLD, SIG_IGN);
        _isrunning = true;

        while(_isrunning)
        {
            InetAddr client;
            SockSPtr newsock = _listensock->Accepter(&client);
            if(newsock == nullptr)
            {
                continue;
            }
            LOG(INFO, "get a new link, client info : %s  , sockfd is %d \n", client.AddrStr().c_str(), newsock->Sockfd());


            //Version 2 --- 多线程版本 不能关闭sockfd 因为线程间共享
            pthread_t tid;
            ThreadData* td = new ThreadData(newsock, this, client);
            pthread_create(&tid, nullptr, Execute, td); //新线程进行分离 不设置join

        }

        _isrunning = false;
    }
    //设为static 去掉this 参数 
    static void* Execute(void *args)
    {
        //分离
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);
        std::string requeststr;
        ssize_t n = td->_sockfd->Recv(&requeststr); //不做请求分离了 太浪费时间
        if(n > 0)
        {
            std::string responsestr = td->_self->_service(requeststr);
            td->_sockfd->Send(responsestr);
        }

        
        td->_sockfd->Close();
        delete td;

        return nullptr;
    }

    ~TcpSever()
    {}


private:
    uint16_t _port;
    SockSPtr _listensock;
    bool _isrunning;
    service_t _service;
};